package controls.questions {
	
	import events.ExperimentEvent;
	
	import flash.events.EventDispatcher;
	
	import mx.collections.XMLListCollection;
	import mx.controls.Alert;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	/**
	 * @author Brent Kersanske
	 */ 
	public class QuestionLoader extends EventDispatcher	{
		
		private static const SET_ONE:String   = "questionSets/QuestionSet1.xml";
		private static const SET_TWO:String   = "questionSets/QuestionSet2.xml";
		private static const SET_THREE:String = "questionSets/QuestionSet3.xml";
		
		private var questionSetURLs:Vector.<String>;
		
		private var questionService:HTTPService;
		
		private var questionList:XMLListCollection;
		
		private var currentQuestionIndex:Number;
		
		public function QuestionLoader() {
			this.currentQuestionIndex = 0;
			initializeQuestionSets();
			initializeQuestionService();
		}
		
		/**
		 * Initializes the available question sets for random selection.
		 */ 
		private function initializeQuestionSets():void {
			this.questionSetURLs = new Vector.<String> ();
			this.questionSetURLs.push(SET_ONE);
			this.questionSetURLs.push(SET_TWO);
			this.questionSetURLs.push(SET_THREE);
		}
		
		private function initializeQuestionService():void {
			this.questionService = new HTTPService();
			this.questionService.resultFormat = HTTPService.RESULT_FORMAT_E4X;
			this.questionService.addEventListener(FaultEvent.FAULT, handleHTTPServiceFault);
			this.questionService.addEventListener(ResultEvent.RESULT, handleQuestionsResult);
		}
		
		public function loadRandomQuestionSet():void {
			this.questionService.url = getRandomQuestionSetURL();
			this.questionService.send();
		}
		
		/**
		 * Gets a random question set url for loading.
		 */ 
		private function getRandomQuestionSetURL():String{
			return this.questionSetURLs[randomInRange(0, this.questionSetURLs.length - 1)];
		}
		
		/**
		 * Helper function for getting a random number in  a range.
		 */ 
		private function randomInRange(min:Number, max:Number):Number {
			var scale:Number = max - min;
        	return Math.round(Math.random() * scale + min);
		}
		
		/**
		 * 
		 */ 		
		private function handleHTTPServiceFault(event:FaultEvent):void {
			Alert.show(event.fault.faultString);
		}
		
		/**
		 * 
		 */ 
		private function handleQuestionsResult(event:ResultEvent):void {
			var xmlList:XMLList = XML(event.result).multipleChoiceQuestion;
	        this.questionList 	= new XMLListCollection(xmlList);
            dispatchEvent(new ExperimentEvent(ExperimentEvent.QUESTION_LOADING_COMPLETE, true, false));
		}		
				
		/**
		 * Are there any more questions to answer?
		 */ 
		public function moreQuestionsAvailable():Boolean {
			if(this.questionList != null) {
				return this.currentQuestionIndex < this.questionList.length;
			} else {
				return false;
			}
		}
		
		/**
		 * Gets the next question in the question set.
		 */ 
		public function getNextQuestion():MultipleChoiceQuestion {
			var question:XML     		 		    = (this.questionList.getItemAt(this.currentQuestionIndex) as XML);
			var nextQuestion:MultipleChoiceQuestion = deriveQuestion(question);
			this.currentQuestionIndex++;
			return nextQuestion;
		}
		
		/**
		 * Derives a formatted question from an XML expression. 
		 */ 
		private function deriveQuestion(mcQuestion:XML):MultipleChoiceQuestion {
			var newQuestion:MultipleChoiceQuestion = new MultipleChoiceQuestion();
			newQuestion.questionID		   = mcQuestion.@id + "-" + mcQuestion.@form;
			newQuestion.questionHeaderText = "Question " + (this.currentQuestionIndex + 1) + " of " + this.questionList.length;
			newQuestion.scenarioText 	   = mcQuestion.scenario.@value;
			newQuestion.questionText       = mcQuestion.question.@value;
			newQuestion.correctOption	   = mcQuestion.options.@correctOption;
			var optionsList:XMLList        = mcQuestion.options.option;
			newQuestion.option1Text 	   = optionsList[0].@value;
			newQuestion.option2Text 	   = optionsList[1].@value;
			newQuestion.option3Text		   = optionsList[2].@value;
			newQuestion.option4Text 	   = optionsList[3].@value;
			newQuestion.option5Text        = optionsList[4].@value;
			return newQuestion;
		}
	}
}